;;
;; myang @ 
;;

;; inhibit startup message
(setq inhibit-startup-message t)

;;(setq debug-on-error t)

(set-background-color "#fff1e0")

(setq-default indent-tabs-mode nil)
(setq tab-width 2)
;; (M-x tabify)
;; (M-x untabify)

(scroll-bar-mode 0)
(tool-bar-mode 0)
(menu-bar-mode 0)
;;(line-number-mode 1)

(global-hl-line-mode t)

(global-font-lock-mode t)

(setq default-major-mode 'text-mode)

(column-number-mode t)

(fset 'yes-or-no-p 'y-or-n-p)

;; highlight the region between the MARK and the point
(transient-mark-mode t)

;; highlight matching parentheses, which seems unnecessary
;; (show-paren-mode 1)

;; set the beep sound, it seems 'ok is a good option
;;(set-message-beep 'ok)

;; prompt you before closing
(setq confirm-kill-emacs 'yes-or-no-p)

;; disable file backup
(setq make-backup-files nil)

(setq visible-bell t)

(setq binary-process-input t)
(setq w32-quote-process-args ?\")


(setq blink-matching-paren 't)
;; blink-matching-delay, the default is 1
;; M-x show-paren-mode

;; next-screen-context-lines, by default, it is 2
;; scroll-preserve-screen-position

;; default-case-fold-search
(setq default-case-fold-search 't)

;;(set-default-font "-raster-Sheldon-normal-normal-normal-*-12-*-*-*-c-*-iso8859-1")
;;(set-default-font "-raster-Sheldon-normal-normal-normal-*-11-*-*-*-c-*-iso8859-1")
;;(set-default-font"-raster-Sheldon Narrow-normal-normal-normal-*-*-*-*-*-c-*-iso8859-1")
;;(set-default-font "-raster-Fixedsys-normal-normal-normal-mono-*-*-*-*-c-*-iso8859-1")
;;(set-default-font "-raster-ProFontWindows-normal-normal-normal-*-12-*-*-*-c-*-iso8859-1")

;;(set-default-font "-outline-Andale Mono-normal-normal-normal-mono-13-*-*-*-c-*-iso8859-1")

;;(set-default-font "-outline-Liberation Mono-normal-normal-normal-mono-12-*-*-*-c-*-iso8859-1")

(set-default-font "-outline-Monaco-normal-normal-normal-mono-12-*-*-*-c-*-iso8859-1")

;;(default-font
;;"-outline-Arial-normal-normal-normal-sans-14-*-*-*-p-*-windows-1258")
;;(set-default-font
;;"-outline-Lucida Console-normal-normal-normal-mono-12-*-*-*-c-*-iso10646-1")
;;"-outline-Consolas-normal-normal-normal-mono-12-*-*-*-c-*-iso10646-1")
;;"-raster-Courier-normal-normal-normal-mono-9-*-*-*-c-*-iso8859-1")
;;"-outline-Courier New-normal-normal-normal-mono-12-*-*-*-c-*-iso8859-1")
;;1l
;;
;; maximize the frame -- 61488
;; to restore the frame -- 61728
;;
;; (w32-send-sys-command 61488)
;; Windows' WM_SYSCOMMAND message
(defun w32-maximize-frame ()
  "Maximize the current frame"
  ;;(interactive)
  (w32-send-sys-command 61488))
;;(add-hook 'window-setup-hook 'w32-maximize-frame t)


;; disable end-of-line conversion
(setq inhibit-eol-conversion 't)
;; auto-coding-regexp-alist
(add-to-list 'auto-coding-regexp-alist '("\\.*" . no-conversion))



(defun toggle-color ()
  ""
  (interactive)
  (let ()
    (set-background-color
     (if (string= "#3a6ea5" (frame-parameter nil 'background-color)) "#ffffff"
       "#3a6ea5"))
    (set-foreground-color
     (if (string= "#ffffff" (frame-parameter nil 'foreground-color)) "#000000"
       "#ffffff"))
    ))



(defun load-files (directory &rest excluded)
  "Load all EL files in the specified directory.
Skip all the files specified by the argument excluded."
  (let (file-name to-load)
    (dolist (each (directory-files directory 't ".*\\.el$"))
      (setq file-name (file-name-nondirectory each))
      (setq to-load 't)
      ;;(message file-name)
      (setq to-load
            (catch 'skip
              (if (string= file-name "common.el")
                  (progn 
                    (message "Skip [common.el] itself.")
                    (throw 'skip nil)))
              (dolist (ex excluded 't)
                (if (string= file-name ex) (throw 'skip nil))
                )))
      (if to-load
          (load-file each)))
    )
  )


(defun d2u ()
  "Convert a file ending with DOS format to UNIX, ie from \r\n to \r."
  (interactive)
  (let ()
    (call-process "d2u" nil nil nil buffer-file-name)
    (revert-buffer 't 't 't)))


(defun mv (to-file-name)
  "Rename the file associated with the current buffer
and reload the renamed file."
  (interactive "FRename to: ")
  (let ((current-file-name (buffer-file-name)))
    (rename-file current-file-name to-file-name
                 ;;(concat
                 ;;(file-name-directory current-file-name) "/" to-file-name)
                 ;; any number means asking for user's confirmation
                 0
                 )
    ;;(rename-buffer to-file-name)
    (kill-buffer)
    (find-file to-file-name)
    ))


(defun cp (dest)
  "Copy the file associated with the current buffer 
to the given destination. If the supplied dest is a directory, 
the file is only copied there; otherwise, the file is copied there 
and the file name is changed as well."
  (interactive "FCopy to: ")
  (let ((current-file-name (buffer-file-name))
        (dest-file))

    (if (file-directory-p dest)
        (setq dest-file
              (concat dest "/"
                      (file-name-nondirectory current-file-name)))
      (setq dest-file dest))

    (copy-file current-file-name dest-file
               ;; any number means asking for user's confirmation
               0)

    (find-file dest-file))
  )

(global-set-key (kbd "C-c j") 'join-line)

;;
;; Move the point to the first non-whitespace character.
;; back-to-indentation, bound to M-m by default

;; nl : new line
(defun nl (lines)
  ""
  (interactive "p")
  (end-of-line)
  (newline lines)
  (indent-for-tab-command)
  )
(global-set-key (kbd "C-c n") 'nl)

;; pl - open a new before the current line
(defun pl (lines)
  ""
  (interactive "p")
  (beginning-of-line)
  (open-line lines)
  (indent-for-tab-command)
  )
(global-set-key (kbd "C-c o") 'pl)



(defun bkup ()
  "Back up the file associated with the current buffer
by appending the file name with a ~."
  (interactive)
  (let ((bkup-file-name
         (concat (file-name-nondirectory buffer-file-name) "~")))
    (rename-file buffer-file-name bkup-file-name 0)
    (kill-buffer)
    (find-file bkup-file-name)
    )
  )


(defun rm ()
  (interactive)
  (if (not (yes-or-no-p
            (concat "Really delete " buffer-file-name "?"))) nil
    (delete-file buffer-file-name)
    (message "File %s is deleted." buffer-file-name)
    (kill-buffer)
    )
  )


(defun nf (fn args)
  "Insert a template of function into the current buffer."
  (interactive "sFunction name: \nsArguments: ")
  (let (interactivep)
    (setq interactivep (yes-or-no-p "Is it an interactive function?"))
    (nl 2)
    (insert (concat "\(defun " fn  " ("
                    (if args args "")
                    ")\n"))
    (indent-for-tab-command)
    (insert "\"\"\n")

    (if interactivep
        (progn
          (indent-for-tab-command)
          (insert "(interactive)\n")))

    (indent-for-tab-command)
    (insert "(let ()\n")

    (indent-for-tab-command)
    (insert ")\n")
    
    (indent-for-tab-command)
    (insert ")\n")
    )
  )


(defun chomp (str)
  "Chomp leading and tailing whitespace from STR."
  (let ((s (if (symbolp str) (symbol-name str) str)))
    (replace-regexp-in-string "\\(^[[:space:]\n]*\\|[[:space:]\n]*$\\)" "" s)))


(defun reload-buffer-file ()
	""
	(interactive)
	(let()
    ;;(load-file load-file-name)
    (load-file (buffer-file-name))
    )
	)
(global-set-key (kbd "C-c l") 'reload-buffer-file)


(defun comment-function ()
	""
	(interactive)
	(let ()
    (mark-defun)
    (comment-region (region-beginning) (region-end))
    (deactivate-mark)
    )
  )

(defun uncomment-function ()
  ""
  (interactive)
  (let ()
    )
  )

(defun is-root (dir)
  (or
   (or (string= "/" dir)
       (string= "c:" dir))
   (string= "c:/" dir))
  )


(defun set-env (var-name &optional new-val replace)
  ""
  (let ((old-val (getenv var-name)))
    (if (or (not old-val) replace)
        (setenv var-name new-val))))



(defun append-env (var-name new-val)
  ""
  (let ((old-val (getenv var-name)))
    (setenv var-name
            (if old-val (concat new-val " " old-val)
              new-val))))

;;
;;load-file-name
;;with-temp-buffer
;;tab-to-tab-stop
;;M-^ delete-indention; the opposite of C-j
;;indent-for-tab-command
;;C-x l; shows the number of the lines
;;mapconcat
;;function
;;ncons
;;identity
;;transpose-lines C-x C-t

;;C-<return>

(defun list-to-string (list &optional separator)
  ""
  (mapconcat 'identity (flatten list) (or separator " ")))


(defun comment-line (flag comm)
  ""
  (let (line pos1 pos2 indent forward)
    (save-excursion
      (back-to-indentation)
      (setq line (chomp (buffer-substring-no-properties
                         (point) (line-end-position))))
      (setq pos1 (string-match (concat "^" flag  "+") line))
      (setq pos2 (string-match (concat "[^" flag "[:space:]]") line))
      (if (and (not pos1) (not pos2)) ;; empty line
          (progn (insert comm) (setq indent 't) (setq forward 't))
        (if (not pos2) ;; commented empty line
            (progn (delete-char (length line)) (setq indent 't))
          (if pos1 (delete-char pos2) ;; commented line
            (insert comm)))) ;; uncommented line
      )
    (if indent (indent-for-tab-command))
    (if forward (forward-char (length comm)))
    ))


(defun comment-lisp-line ()
  (interactive)
  (comment-line ";" ";;"))
(global-set-key (kbd "C-;") 'comment-lisp-line)


(defun flatten (list)
  ""
  (let ((rslt '()))
    (dolist (elt list rslt)
      (if (listp elt) (setq rslt (append rslt (flatten elt)))
        (setq rslt (append rslt (list elt)))
        ))))


(defun zip ()
  "Zip the current buffer file."
  (interactive)
  (let ((zip-file (concat buffer-file-name ".zip")))
    (call-process "zip" nil "*zip*" nil zip-file buffer-file-name)
    (message "Current buffer file is zipped to %s." zip-file)
    ))
(global-set-key (kbd "C-c z") 'zip)


(defun strip-ctrl-m (proc str)
  "This process filter function to remove the ending ^M
from the process output.(set-process-filter proc 'strip-ctrl-m)"
  (let ((buf (process-buffer proc)))
    (with-current-buffer (if buf buf)
      (insert (replace-regexp-in-string
               (concat (char-to-string 13) "$") ;; construct ^M
               "" str))
      )))


(defun directory-plus-file (directory file-name)
  ""
  (concat-file-names directory file-name))


(defun concat-file-names (&rest file-names)
  ""
  (let ((file-name) (result ""))
    (dolist (file-name file-names result)
      (setq result
            (concat-two-file-names result file-name)))))
;;test concat-file-names
;;(concat-file-names "/abc/" "/ef" "ghi/" "dd" "/opi")
;;(concat-file-names "abc" "efg")

(defun concat-two-file-names (first second)
  ""
  (let ((first-ending-with-slash
         (and (> (length first) 0)
              (string= "/" (substring first -1))))
        (second-starting-with-slash
         (and (> (length second) 0)
              (string= "/" (substring second 0 1)))))
    (if (and first-ending-with-slash second-starting-with-slash)
        (concat first (substring second 1))
      (if (or first-ending-with-slash second-starting-with-slash)
          (concat first second)
        (concat first
                (if (or (= 0 (length first))
                        (= 0 (length second))) "" "/")
                second)))))
;;test concat-two-file-names
;;(concat-two-file-names "/" "/edf")
;;(concat-two-file-names "abc" nil)
;;(concat-two-file-names "abc/" "edf")
;;(concat-two-file-names "abc" "/edf")



(defun w32-ie (&optional url)
  (interactive "MURL: ")
  ""
  (w32-start-process
   "C:\\Program Files\\Internet Explorer\\iexplore.exe"
   (if url url "")))


(defun w32-firefox (&optional url)
  (interactive "MURL: ")
  ""
  (w32-start-process
   "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
   (if url url "")))


(defun w32-start-process (proc &rest arg)
  ""
  (let ((proc-name (concat "w32-" proc)))
    (apply 'start-process proc-name nil proc arg)))


(defun copy-word ()
  (interactive)
  (let ((the-word (thing-at-point 'word)))
    (kill-new the-word)
    (message "[%s] copied to the kill-ring" the-word)
    ;;(push the-word kill-ring)
    ;;(setq kill-ring-yank-pointer kill-ring)
    ))
(global-set-key (kbd "<f2>") 'copy-word)

(defun copy-region (start end)
  (if (>= start end) nil
    (kill-new
     (buffer-substring start end))))

(defun copy-line (lines)
  (interactive "p")
  (if (= 1 lines)
      (copy-region (line-beginning-position)
                   (line-end-position))
    (if (> lines 0)
        (copy-region (line-beginning-position)
                     (line-end-position lines))
      (copy-region (line-beginning-position (+ 1 lines))
                   (line-end-position))
      )))
(global-set-key (kbd "<f5>") 'copy-line)

(defun duplicate-line (lines)
  ""
  (interactive "p")
  (copy-line lines)
  (nl 1) (yank))
(global-set-key (kbd "C-<f5>") 'duplicate-line)

(defun copy-line-after-point ()
  (interactive)
  (copy-region (point) (line-end-position)))
(global-set-key (kbd "<f6>") 'copy-line-after-point)

(defun copy-line-before-point ()
  (interactive)
  (copy-region (line-beginning-position) (point)))
(global-set-key (kbd "<f7>") 'copy-line-before-point)

(defun delete-line ()
  (interactive)
  (delete-region
   (line-beginning-position) (line-end-position)))
(global-set-key (kbd "<f8>") 'delete-line)

(defun delete-line-before-point ()
  (interactive)
  (delete-region
   (line-beginning-position) (point)))
(global-set-key (kbd "<f9>") 'delete-line-before-point)


(defun putty (host)
  (interactive "sHost: " )
  (let ((putty-exe "c:/myang/apps/putty.exe"))
    (start-process "putty" nil putty-exe host)
    )
  )
(global-set-key (kbd "C-M-<f1>") 'putty)


(defun transparency (value)
  "Sets the transparency of the frame window. 0=transparent/100=opaque"
  (interactive "nTransparency Value 0 - 100 opaque:")
  (set-frame-parameter (selected-frame) 'alpha value))
;;(transparency 100)


(setq max-lisp-eval-depth 40000)

(setq max-specpdl-size 100000)



(defun new-proc-sync (p-executable
                      &optional p-options p-buffer-options)
  "Start a new process in synchronous mode."
  (new-proc p-executable
            p-buffer-options
            (lambda (p-buffer)
              (apply 'call-process p-executable nil p-buffer nil p-options)
              p-buffer))
  )


(defun new-proc-async (p-executable
                       &optional p-options p-buffer-options)
  "Start a new process in asynchronous mode"
  (new-proc p-executable
            p-buffer-options
            (lambda (p-buffer)
              (if (get-buffer-process p-buffer) nil
                (apply 'start-process (buffer-name p-buffer) p-buffer
                       p-executable p-options)
                p-buffer)))
  )


(defun new-proc-sh (p-executable
                    &optional p-options p-buffer-options)
  ""
  (new-proc p-executable
            (nconc p-buffer-options '((p-not-create . t)))
            (lambda (p-buffer-name)
              (apply 'make-comint p-buffer-name p-executable nil p-options)
              (get-buffer (concat "*" p-buffer-name "*"))))
  )


(defun new-proc (p-executable
                 p-buffer-options
                 func)
  "Start a new process.
 <p-options> is a list like (\"-cp\" \"x;y;z\" \"-Xmx512M\")
 <p-buffer-options> is an alist, which contains following keys:
 p-not-create => create the buffer;
 p-name => buffer name associated with the process;
 p-clear => indicating whether to clear the buffer before run;
 p-readonly => is the buffer readonly;
 p-pop => whether display the buffer or not;
 p-new-frame => display the buffer in a new frame."

  (let ((the-buffer) (buffer-name
                      (cdr (assoc 'p-name p-buffer-options))))
    (if (not buffer-name) (setq buffer-name (concat "*" p-executable "*")))
    (setq the-buffer
          (if (cdr (assoc 'p-not-create p-buffer-options)) nil
            (get-buffer-create buffer-name)))
    (if the-buffer
        (with-current-buffer the-buffer
          (setq buffer-read-only nil)
          (if (cdr (assoc 'p-clear p-buffer-options)) (erase-buffer))
          (setq buffer-read-only (cdr (assoc 'p-readonly p-buffer-options)))
          ))

    (setq the-buffer (funcall func (if the-buffer the-buffer buffer-name)))

    (if (cdr (assoc 'p-pop p-buffer-options))
        (progn
          (setq pop-up-windows nil)
          (pop-to-buffer the-buffer)
          ))
    ))


(defun directory-files-recursively (directory &optional full match)
  ""
  (let ((rlst (list "")))
    ;;(message "check [%s]" (expand-file-name directory))
    (dolist (fname (directory-files directory full))
      ;;(message "%s is a folder: %s" fname (file-directory-p fname))
      (if (equal "." (substring fname -1)) ()
        (if (file-directory-p fname)
            (nconc rlst (directory-files-recursively
                         (if full fname
                           (concat-file-names directory fname))
                         full match))
          (if (or (not match) (string-match match fname))
              (nconc rlst (list fname)))
          )))
    (cdr rlst))
  )


(defun directory-files-recursively-2 (directory &optional full
                                                matcher)
  ""
  (let ((rlst (list "")))
    (dolist (fname (directory-files directory full))
      (if (equal "." (substring fname -1)) ()
        (if (file-directory-p fname)
            (nconc rlst (directory-files-recursively-2
                         (if full fname
                           (concat-file-names directory fname))
                         full matcher))
          (if (or (not matcher) (funcall matcher fname))
              (nconc rlst (list fname)))
          )))
    (cdr rlst)))


(defun diary2 ()
  (interactive)
  (find-file "~/diary"))
(add-to-list 'auto-mode-alist '("diary$" . diary-mode))


(defun get-env (var &optional ignore)
  "Get the value of environmental variable VAR.
If IGNORE is not nil, value is nil if VAR is undefined;
otherwise, an error message is signaled."
  (let ((v (getenv var)))
    (if v v
      (if (not ignore )(error "[%s] is not define." var)))))


;; (quoted-insert is a very useful function
;; to insert special characters
;; the default keybinding is C-q


;;(require 'ido)

(defun unzip (buffer-options zipfile &rest options)
  ;;(message "unzip file: %s" zipfile)
  (new-proc-sync "unzip" (nconc options (cons zipfile nil))
                 buffer-options)
  )

(defun to-win-path (path)
  "Convert a Unix path to a Windows path. 
The Emacs\'s functions: buffer-file-name and file-name-directory return 
Windows paths separated by slashes, such as \"c:/Windows/system32\", which
are not conveniently usable outside of Emacs. This function converts
these paths to the native Windows style, such as \"c:\\Windows\\system32\".
"
  (let (win-path)
    (dolist (file (split-string path "/"))
      (setq win-path (concat win-path
                             (concat file
                                     (if (eq "" file) "" "\\")))))
    (substring win-path 0 -1)))